package com.fang.gateway.security.config;

import com.fang.gateway.entity.bo.SecurityProperties;
import com.fang.gateway.security.filter.FluxJwtAuthenticationTokenFilter;
import com.fang.gateway.security.handler.*;
import com.fang.gateway.security.service.AuthorityService;
import com.fang.gateway.security.service.FluxReactiveAuthenticationManager;
import com.fang.gateway.security.service.FluxSecurityPermissionEvaluator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.web.cors.CorsConfiguration;

import javax.annotation.Resource;
/**
 * @Description
 * @Author Bernie_fang
 * @Date 2025/3/4 22:37
 **/

/**
 * @Description EnableWebFluxSecurity权限验证配置
 * @Author JL
 * @Version V1.0
 */
@Slf4j
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class WebFluxSecurityConfig {

    @Resource
    private AuthorityService authorityService;

    @Resource
    private FluxReactiveAuthenticationManager fluxReactiveAuthenticationManager;

    @Resource
    private FluxJwtAuthenticationTokenFilter fluxJwtAuthenticationTokenFilter;

    @Resource
    private FluxAuthenticationSuccessHandler fluxAuthenticationSuccessHandler;

    @Resource
    private FluxAuthenticationFailureHandler fluxAuthenticationFailureHandler;

    @Resource
    private FluxSecurityPermissionEvaluator fluxSecurityPermissionEvaluator;

    @Resource
    private FluxLogoutSuccessHandler fluxLogoutSuccessHandler;

    @Resource
    private FluxAccessDeniedHandler fluxAccessDeniedHandler;

    @Resource
    private FluxAuthenticationEntryPoint fluxAuthenticationEntryPoint;

    @Resource
    private SecurityProperties securityProperties;

//    /**
//     * 提供用于获取UserDetails的Service
//     * @return
//     */
//    @Bean
//    public ReactiveAuthenticationManager authenticationManager() {
//        this.log.info("==> ReactiveAuthenticationManager");
//        return new UserDetailsRepositoryReactiveAuthenticationManager(authorityService);
//    }

    /**
     * http请求路径权限与过滤链配置
     * @param http
     * @return
     */
    @Bean
    public SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
        log.info("==> SecurityWebFilterChain");
        http
                .csrf().disable()
                .cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues())
                .and()
                .httpBasic().disable()
                .securityContextRepository(fluxJwtAuthenticationTokenFilter)    // 自定义接口权限过滤器
                .formLogin()
                .authenticationManager(fluxReactiveAuthenticationManager)       // 自定义登录验证
                .authenticationSuccessHandler(fluxAuthenticationSuccessHandler)     // 登录成功处理
                .authenticationFailureHandler(fluxAuthenticationFailureHandler)     // 登录失败处理
                .and()
                .authorizeExchange(exchanges -> exchanges
                                .pathMatchers(securityProperties.getPermitAll()).permitAll() // 放行这些路径
                                .anyExchange().access(fluxSecurityPermissionEvaluator)      // 自定义权限注解验证
    //                        .anyExchange().authenticated()
                )
                .logout(s -> s.logoutSuccessHandler(fluxLogoutSuccessHandler))      // 登出成功处理
                .exceptionHandling()
                .accessDeniedHandler(fluxAccessDeniedHandler)               // 权限拒绝处理
                .authenticationEntryPoint(fluxAuthenticationEntryPoint);    // 未验证(登录)处理
        return http.build();
    }

}
